package com.app.client;

import com.app.game.chat.Message;
import com.app.game.other.Player;
import com.app.head.Head;
import com.app.head.HeadsConst;
import com.app.head.impl.HeadMessage;
import com.app.head.impl.HeadPlayer;
import com.app.head.impl.HeadReady;
import com.app.head.impl.HeadRoundDone;
import com.app.lan.Receiver;
import com.app.lan.Sender;
import com.app.observers.ServerObserver;
import com.app.observers.ServerSubject;
import com.app.task.Task;
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;

public class ServerHandler extends Task implements ServerSubject {

    private ObjectInputStream input;
    private ObjectOutputStream output;
    //private Receiver<HashMap<Integer, Player>> playerListReceiver;
    private Receiver<Head> headReceiver;
    //private Receiver<Integer> integerReceiver;
    //private Receiver<Message> msgReceiver;
    //private Receiver<Player> playerReceiver;
    //private Sender<Player> playerSender;
    private Sender<Head> headSender;
    //private Sender<Message> msgSender;
    private Head headPlayer = new HeadPlayer();
    private Head headReady = new HeadReady();
    private Head headRoundDone = new HeadRoundDone();
    private Head headmsg = new HeadMessage();
    ArrayList<ServerObserver> observers = new ArrayList<ServerObserver>();

    public ServerHandler(Socket socket) {
        try {
            input = new ObjectInputStream(new BufferedInputStream(
                    socket.getInputStream()));
            output = new ObjectOutputStream(new BufferedOutputStream(
                    socket.getOutputStream()));

            //playerListReceiver = new Receiver<HashMap<Integer, Player>>(input);
            headReceiver = new Receiver<Head>(input);
            //integerReceiver = new Receiver<Integer>(input);
            //msgReceiver = new Receiver<Message>(input);

            //playerSender = new Sender<Player>(output);
            headSender = new Sender<Head>(output);
            //msgSender = new Sender<Message>(output);

        } catch (IOException e) {

            e.printStackTrace();
        }
    }

    @Override
    protected void task() {
        try {
            Head head = headReceiver.receive();
            int object = head.getObjectId();
            System.out.println(object);
            switch (object) {
                case HeadsConst.PLAYER:
                    playerDelivery((Player) head.getObject());
                    break;
                case HeadsConst.PLAYER_LIST:
                    playerListDelivery((HashMap<Integer, Player>) head.getObject());
                    break;
                case HeadsConst.GAME_STARTING:
                    gameStartDelivery();
                    break;
                case HeadsConst.GAME_ENDING:
                    gameOverDelivery();
                    break;
                case HeadsConst.RESULT:
                    roundResultDelivery((Integer) head.getObject());
                    break;
                case HeadsConst.READY_NOTIFICATION:
                    readyNotificationDelivery((Integer) head.getObject());
                    break;
                case HeadsConst.MESSAGE:
                    messageDelivery((Message) head.getObject());
                    break;


            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void playerDelivery(Player player) {

        for (ServerObserver ob : observers) {
            ob.updatePlayer(player);
        }

    }

    private void playerListDelivery(HashMap<Integer, Player> players) {

        for (ServerObserver ob : observers) {
            ob.updatePlayers(players);
        }


    }

    private void roundResultDelivery(Integer result) {

        for (ServerObserver ob : observers) {
            ob.updateResult(result);
        }
    }

    private void messageDelivery(Message msg) {

        for (ServerObserver ob : observers) {
            ob.updateMessage(msg);
        }


    }

    private void gameStartDelivery() {

        for (ServerObserver ob : observers) {
            ob.updateGameStarting();
        }

    }

    private void gameOverDelivery() {
        for (ServerObserver ob : observers) {
            ob.updateGameOver();
        }

    }

    private void readyNotificationDelivery(Integer player) {

        for (ServerObserver ob : observers) {
            ob.updateReadyNotification(player);
        }


    }

    public void sendPlayer(Player player) {
        headPlayer.setObject(player);
        headSender.setObject(headPlayer);
        //playerSender.setObject(player);
        try {
            headSender.send();
            //playerSender.send();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void sendRoundDone() {
        headRoundDone.setObject(true);
        headSender.setObject(headRoundDone);
        try {
            headSender.send();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void sendReady() {
        headReady.setObject(true);
        headSender.setObject(headReady);
        try {
            headSender.send();
        } catch (IOException e) {

            e.printStackTrace();
        }
    }

    public void sendMessage(Message msg) {
        Head headMsg = new HeadMessage();
        headMsg.setObject(msg);
        
        headSender.setObject(headMsg);
        //msgSender.setObject(msg);
        try {
            headSender.send();
            //msgSender.send();
        } catch (IOException e) {

            e.printStackTrace();
        }
    }

    public void registerObserver(ServerObserver observer) {
        observers.add(observer);
    }

    public void removeObserver(ServerObserver observer) {
        observers.remove(observer);
    }
}
